dex solidity配置

dex solidity配置


基础属性 订单簿交易

  • 收费账号 address public feeAccount;
  • 费率 uint256 public feePrecent;
  • 交易所名字 string public name;
  • 初始化ETH的地址 address constant ETHER = address(0);
  • 账簿 mapping(address => mapping(address => uint256)) public tokens;
  • 订单结构体
1
2
3
4
5
6
7
8
9
10
// 订单结构体
struct _Order {
uint256 id; // 表示
address user; // 发起order用户
address tokenGet; // 需要token的地址
uint256 amountGet; // 需要token数量
address tokenGive; // 消耗token的地址
uint256 amountGive; // 消耗token的数量
uint256 timestamp; // 时间戳 block.timestamp 关键字 block
}
  • 订单记录 mapping(uint256 => _Order) public orders;
  • 订单数量 uint256 public orderCount;
  • 订单取消标识 用于前端区分 且可用于判断是否完成了订单 mapping(uint256 => bool) public orderCancelled;
  • 订单交易成功标识 mapping(uint256 => bool) public orderFilled;

功能

构造函数初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// constructor(address _feeAccount, uint256 _feePrecent) {
// feeAccount = _feeAccount;
// feePrecent = _feePrecent;
// }

// 删除 constructor,改用 function 函数 部署代理合约的时候,使用构造函数会报错,代理合约是为了升级合约不用改变原合约地址
function initialize(
address _feeAccount,
uint256 _feePrecent,
string memory _name
) public {
feeAccount = _feeAccount;
feePrecent = _feePrecent;
name = _name;
}

depositEth 存eth

1
2
3
4
5
6
7
8
event Deposit(address indexed _token, address indexed _user, uint256 _amount, uint256 _balance);
// depositEth paybable可交易eth
function depositEth() public payable {
// 地址簿
tokens[ETHER][msg.sender] += msg.value;
// 触发事件 记录上链 相当于log
emit Deposit(ETHER, msg.sender, msg.value, tokens[ETHER][msg.sender]);
}

depositToken 存某token

1
2
3
4
5
6
7
8
9
10
11
// depositEth paybable可交易eth
function depositToken(address _token, uint256 _amount) public {
// 账簿
tokens[_token][msg.sender] += _amount;

// 需要msg.sender授权交易所交易CysToken
// 将 _token 地址转换为 CysToken类型 调用CysToken合约方法将用户cystoken转入交易所地址
CysToken(_token).transferFrom(msg.sender, address(this), _amount);

emit Deposit(_token, msg.sender, _amount, tokens[_token][msg.sender]);
}

withdrawEther 提取eth

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
event WithDraw(address indexed _token, address indexed _user, uint256 _amount, uint256 _balance);
error amountError();
function withdrawEther(uint256 _amount) public payable {
// 账簿记录
if (tokens[ETHER][msg.sender] < _amount) {
revert amountError();
}
tokens[ETHER][msg.sender] -= _amount;

// 调用ETH的transfer方法将ETH从交易所提出给用户
// 从交易所把ETH转给用户 ERC20 交易方法标准
payable(msg.sender).transfer(_amount);

emit WithDraw(ETHER, msg.sender, _amount, tokens[ETHER][msg.sender]);
}

withdrawToken 提取某token

1
2
3
4
5
6
7
8
9
10
11
12
// withdrawTokens
function withdrawToken(address _token, uint256 _amount) public {
// 判断:地址不为0,账簿上数量
require(_token != ETHER);
require(tokens[_token][msg.sender] >= _amount);
// 账簿操作
tokens[_token][msg.sender] -= _amount;
// 从交易所转给用户
require(CysToken(_token).transfer(msg.sender, _amount));
// 记录事件
emit WithDraw(_token, msg.sender, _amount, tokens[_token][msg.sender]);
}

makeOrder 创建订单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//makeOrder
function makeOrder(address _tokenGet,address _tokenGive,uint256 _amountGet,uint256 _amountGive ) public {

orderCount++;
// 记录orderlist中
orders[orderCount] = _Order(
orderCount,
msg.sender,
_tokenGet,
_amountGet,
_tokenGive,
_amountGive,
block.timestamp
);

emit Order(orderCount,msg.sender,_tokenGet,_amountGet,_tokenGive,_amountGive,block.timestamp);
}

cancelOrder 取消订单

1
2
3
4
5
6
7
8
9
10
11
// cancelOrder
// 设置orderCancelled中该订单为true即可 不需要删除记录
function cancelOrder(uint256 _id) public {
_Order memory _order = orders[_id];
require(address(_order.user) == msg.sender);
require(_order.id == _id);

orderCancelled[_id] = true;

emit Cancel(_id, msg.sender, _order.tokenGet, _order.amountGet, _order.tokenGive, _order.amountGive, block.timestamp);
}

fillOrder 完成订单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// fillOrder 完成订单只发生于交易所内 操作订单簿上的数据
function fillOrder(uint256 _id) public {
_Order memory _order = orders[_id];
require(_order.id == _id); // 订单id是否存在
require(orderCancelled[_id] == false, "Order has been cancelled"); // 订单是否被取消
require(orderFilled[_id] == true, "Order has already been filled"); //订单是否已经被交易
require(_order.user != msg.sender); // 卖家 != 买家

// 账户余额交易 && 手续费
uint256 _feeAmount = _order.amountGive * feePrecent / 100;
// 交易所收取手续费 = 交易者消耗的token数量 * 手续费率
tokens[_order.tokenGet][feeAccount] += _feeAmount; // 交易所收费账户
/*
msg.sender 交易者
_order.tokenGet 交易者要交易的token合约地址 CYST
_order.amountGet 交易者要交易的token数量 10000
_order.tokenGive 交易者要消耗的token合约地址 ETH
_order.amountGive 交易者要消耗的token数量 1
eg: CYST * 10000 => ETH * 1

订单簿中
*/
tokens[_order.tokenGet][msg.sender] += _order.amountGet ;
tokens[_order.tokenGet][_order.user] -= _order.amountGet;
tokens[_order.tokenGive][msg.sender] -= ( _order.amountGive + _feeAmount); // 交易者要消耗的token+手续费
tokens[_order.tokenGive][_order.user] += _order.amountGive;

// 已经交易的订单id
orderFilled[_id] = true;

emit Trade(_order.id,_order.user,_order.tokenGet,_order.amountGet,_order.tokenGive,_order.amountGive,block.timestamp);
}